﻿using System;
using AiFrame.Base.Core.Data.Access;
using AiFrame.Base.Core.Env;
using AiFrame.Base.Core.Plugins;
using AiFrame.Base.Core.Properties;
using AiFrame.InterfaceLib.Configuration;
using AiFrame.InterfaceLib.Data.Patterns;
using AiFrame.InterfaceLib.Data.Provider;
using AiFrame.InterfaceLib.Licenses;
using AiFrame.InterfaceLib.Logs;

namespace AiFrame.Base.Core.MVP
{
    /// <summary>
    /// Diese Klasse stellt den Presenter des Login-Fensters dar.
    /// </summary>
    public class LoginPresenter: IObserver
    {
        private ILoginView _view;
        private AssemblySettings _assemblySettings = new AssemblySettings();

        /// <summary>
        /// The constructor.
        /// </summary>
        /// <param name="loginView">The login view.</param>
        public LoginPresenter(ILoginView loginView)
        {
            _view = loginView;
            _view.ShowOptions(false);
            IsConnected = false;

            // Bei der Provider-Liste als Observer anmelden,
            // um bei Aktualisierungen den aktuellen Stand zu erhalten.
            ProviderRegistration.Instance.Providers.RegisterObserver(this);
            ProviderRegistration.Instance.Providers.BeginUpdate();
            ProviderRegistration.Instance.Providers.EndUpdate();
            
            DatabaseConnection.Instance.Database = Settings.Default.DBName;

            if (ConfigurationProxy.LicenseManager != null)
                LoadLicense();
        }

        /// <summary>
        /// Loads the program's license
        /// </summary>
        private void LoadLicense()
        {
            License license = ConfigurationProxy.LicenseManager.GetLicense();
            // There is a license file
            if (license != null)
            {
                // Enable all controls, if it is not a trial version
                _view.UserNameFieldEnabled = (license.LicenseType == LicenseType.Full);
                _view.PasswordFieldEnabled = (license.LicenseType == LicenseType.Full);
                _view.HostAddressFieldEnabled = (license.LicenseType == LicenseType.Full);
                _view.DBProdiverFieldEnabled = (license.LicenseType == LicenseType.Full);

                // User has a trial license
                if (license.LicenseType == LicenseType.Trial)
                {
                    // Load values from the license file
                    _view.Username = license.UserName;
                    _view.Password = license.Password;
                    _view.HostAddress = license.ServerAddress;

                    DatabaseConnection.Instance.Database = license.DatabaseName;
                    // TODO: DB Provider ?
                }
                else
                {
                    // Standard-Einstellungen laden
                    _view.Username = Settings.Default.DBUsername;
                    _view.HostAddress = Settings.Default.DBHostAddress;

                    try
                    {
                        if (bool.Parse(_assemblySettings["SavePassword"]) == true)
                            _view.Password = Encryption.DecryptString(Settings.Default.DBPassword, EnvironmentVariables.ED_KEY);
                        else
                            _view.FocusPasswordField();
                    }
                    catch (Exception)
                    {
                        LogHandler.GetLogger().Warn("Could not decrypt login password.");
                        _view.Password = "";

                    }
                }
            }
            else
            {
                _view.InformUser("Für diese Software ist keine gültige Lizenz vorhanden. Bitte wählen Sie eine Lizenzdatei aus.");

                // There is no license file.
                string fileName = _view.SelectLicenseFile();
                
                if (!string.IsNullOrEmpty(fileName))
                {
                    // Import license
                    ConfigurationProxy.LicenseManager.ImportLicense(fileName);

                    // Try reload license
                    LoadLicense();    
                }
                else
                {
                    // No file selected, so close the program
                    _view.CloseWindow();
                }

                
            }
        }

        /// <summary>
        /// Is called when the options button is clicked.
        /// </summary>
        public void OnOptionsClick()
        {
            _view.ShowOptions(!_view.AreOptionsDisplayed());
        }

        /// <summary>
        /// Is called when the ok button is clicked.
        /// </summary>
        public void OnConnectClick()
        {
            DatabaseConnection.Instance.CloseSession();

            // Verbindungsdaten abspeichern
            Settings.Default.DBUsername = _view.Username;
            Settings.Default.DBHostAddress = _view.HostAddress;

            if (bool.Parse(_assemblySettings["SavePassword"]) == true)
                Settings.Default.DBPassword = Encryption.EncryptString(_view.Password, EnvironmentVariables.ED_KEY);

            Settings.Default.Save();

            DatabaseConnection.Instance.HostAddress = _view.HostAddress;
            DatabaseConnection.Instance.Username = _view.Username;
            DatabaseConnection.Instance.Password = _view.Password;
            
            ProviderRegistration.Instance.ActiveProvider = _view.SelectedProvider;

            try
            {                
                DatabaseConnection.Instance.GetSession();
                _view.ShowConnectAnimation = true;
                
                IsConnected = true;
                _view.ShowConnectAnimation = false;
                _view.CloseWindow();
            }
            catch (Exception e)
            {
                _view.ShowConnectAnimation = false;
                _view.DisplayError("Die Verbindung zur Datenbank konnte nicht " 
                    + "hergestellt werden: " + e.Message);
                DatabaseConnection.Instance.CloseSession();
            }
            return;
        }

        /// <summary>
        /// Returns the connection status.
        /// </summary>
        public bool IsConnected
        {
            get; private set;
        }

        public void NotifyChanges(object sender, object obj)
        {
            // Falls sender vom Typ ProviderRegistration...
            if (sender == ProviderRegistration.Instance.Providers)
            {
                // Dann soll die Liste der Provider aktualisiert werden.
                foreach (IDbProvider provider in ProviderRegistration.Instance.Providers)
                {
                    _view.ClearAllProviders();
                    _view.AddDbProvider(provider);
                }
                // Wenn min. 1 Provider registriert ist, soll der erste
                // in der Liste ausgewählt werden.
                if (ProviderRegistration.Instance.Providers.Count != 0)
                    _view.SelectedProviderIndex = 0;
            }
        }
    }
}